#include <iostream>
using namespace std;

class Person {
public:
  char sex;
  Person() {
    cout << "Person()" << endl;
  }
  Person(char* name, int age) {
    cout << "Person(char* name, int age)" << endl;
  }
  ~Person() {}
  void say() {
    cout << "Person say()" << endl;
  }
  void say(int i) {
    cout << "Person say()" << i << endl;
    // say();
  }
  void say2() {
    cout << "say2" << name << endl;
  }
  void setAge(int age1) {
    age = age1;
  }
  int getAge() {
    return age;
  }
private:
  char* name;
  int age;
  void setName(char* name1) {
    name = name1;
  }
  char* getName() {
    return name;
  }
protected:
  int salary;
  void setSalary(int salary1) {
    salary = salary1;
  }
  int getSalary() {
    return salary;
  }
};

class Student : public Person {
public:
  // 子类构造函数调用父类的构造函数（记住一点，构造函数不能手动调用，所以不能在{}内些Person::Person(参数列表)）；
  // Student():Person(参数列表) {...}

//   Student() {
//     cout << "Student()" << endl;
//   };
//   Student(char* name, int age) {
//     cout << "Student(char* name, int age)" << endl;
//   };

  void f1() {
    // 父类的 protected 的方法，子类中是可以使用的；
    setSalary(112233);
    printf("salary %d\n", salary);

    // 子类方法调用父类的方法
    // Person::方法名(参数列表);
  }
  // 这个函数和上面的 f1() 构成了重载，那么const的含义是什么呢？
  // const Student stu; stu.f1(); 就会执行这个带有 const 的方法，而不会执行上面那个方法。
  void f1() const {...}

  void f2() {
    // 父类的 private 的方法，子类中是不能直接使用的；自然，成员变量也是不能使用的。
    // setName("hha");
    // printf("name %s\n", name);
  }
  // void say() {
  //   cout << "Student say()" << endl;
  // }
  void say(int i) {
    cout << "Student say()" << i << endl;
    say();
  }
};

// 父类中如果存在重载的函数，比如 f() f(int) f(int,int) 等，如果子类中存在同名的方法（不管是否覆写），那么
// 1，编译报错；
// 2，即使编译通过，子类也无法使用父类的同名的任何方法了。
// 视频中说：在c++中父子类中的同名方法，是没有关联的。
// 子类调用父类的同名方法：stu.Person::f();

// 如果让父子类中的同名方法产生联系呢？方法前加 virtual 关键字，父子类的方法都加。

// 类方法的参数的默认值，只能在 .h 文件中的方法声明时给与默认值，在 .cpp 中定义时不能给予默认值。
// 普通函数的默认值也是这样的。

int main(int argc, char const *argv[]) {
  // Student stu("hah", 33);
  // stu.say();


  Student stu; // 此时就会自动执行无参构造；如果没有无参构造函数，则报错。
  stu.setAge(1122);
  printf("%d\n", stu.getAge());
  // printf("%d\n", stu.age);
  stu.f1();
  stu.f2();
  // printf("salary %d\n", stu.salary); 父类的 protected 的salary ，子类的实例不能直接使用。

  // 情况1：Student 类中有 say()，没有 say(int) 时：
  // stu.say(); // 可以。
  // stu.say(123); // 报错。不管内部是否调用了 say();

  // 情况2：Student 类中有 say(int)，没有 say() 时：
  // stu.say(); // 报错。
  // stu.say(123); // 如果内部没有调用 say()，是可以的；否则报错。

  // Student stu2("gg", 44);
  // stu2.say2();
}